package GUI;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.EnumMap;

import javax.swing.*;

import map.Map;
import map.Resolution;
import mission.Mission;
import mission.MissionStep;

import utilities.RefreshListener;
import utilities.ResultEvent;
import utilities.ResultListener;
import Player.PG;

import controller.ImageLoader;
import controller.MissionEngine;
import controller.LocalManager;

public class MissionPanel extends JPanel implements ResultListener{

	public MissionPanel(Resolution res, RefreshListener refresh, JFrame callerToBlock){
		this.setOpaque(false);
		this.callerToBlock = callerToBlock;
		this.refresh= refresh;
		engine = new MissionEngine();
		missionPanels = new EnumMap<Resolution, JPanel>(Resolution.class);
		this.currentRes = res;
		refreshPanel();
	}
	
	public JPanel createMissionPanel(Resolution res){
		Map map = LocalManager.getMap();
		JPanel globalMap = new JPanel(null);
		globalMap.setOpaque(false);
		globalMap.setPreferredSize(new Dimension(map.getWidth()*res.getFactor(), map.getHeight()*res.getFactor()));
		//player image
		Point p = LocalManager.getPlayerLocation();
		JLabel pg = null;
		PG player = LocalManager.getCurrentPlayer();
		String box = player.getAvatarBox();
        if(box != null)
        	pg = new JLabel(ImageLoader.getPlayerImage(res, box, player.getAvatarNum()));
        else
        	pg = new JLabel(ImageLoader.getPlayerImage(res, "Order of the stick", 1));
		Dimension size = pg.getPreferredSize();
		int gridX = p.x*res.getFactor();
		int gridY = p.y*res.getFactor() - (size.height>res.getFactor() ? (size.height-res.getFactor()) : 0);
		pg.setBounds(gridX, gridY, size.width, size.height);
		globalMap.add(pg);
		
		Mission mission = LocalManager.getCurrentMission();
		MissionStep step = engine.getPossibleStep().get(0);
		Point temp = step.getLocation();
		Point first = p;
		int x1 = first.x*res.getFactor() + res.getFactor()/2;
		int y1 = first.y*res.getFactor() + res.getFactor()/2;
		int x2 = temp.x*res.getFactor() + res.getFactor()/2;
		int y2 = temp.y*res.getFactor() + res.getFactor()/2;
		int w = Math.abs(x1 - x2);
		if(w == 0)
			w = 1;
		int h = Math.abs(y1 - y2);
		if(h == 0)
			h = 1;
		int minX = x1<x2?x1:x2;
		int minY = y1<y2?y1:y2;
		
		//firstLine
		BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		BufferedImage modified = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D)bi.createGraphics();
        Graphics2D g2dModified = (Graphics2D)modified.createGraphics();
        g2d.setPaint(Color.WHITE);
        g2dModified.setPaint(Color.RED);
        g2d.draw(new Line2D.Double(x1-minX, y1-minY, x2-minX, y2-minY));
        g2dModified.draw(new Line2D.Double(x1-minX, y1-minY, x2-minX, y2-minY));
        g2d.dispose();
        g2dModified.dispose();
        JLabel line = new JLabel(new ImageIcon(bi));
        JLabel lineModified = new JLabel(new ImageIcon(modified));
        line.setBounds(minX, minY, w, h);
        lineModified.setBounds(minX, minY, w, h);
        
        
        //first circle
        JLabel circle;
        if(temp != mission.getFinish().getLocation()){
	        bi = new BufferedImage(res.getFactor(), res.getFactor(), BufferedImage.TYPE_INT_ARGB);
	        g2d = (Graphics2D)bi.createGraphics();
	        g2d.setPaint(new Color(255, 0, 0, 150));
	    	g2d.fill (new Ellipse2D.Double(0.34*res.getFactor(), 0.34*res.getFactor(), res.getFactor()/3, res.getFactor()/3));
	    	g2d.dispose();
	    	circle = new JLabel(new ImageIcon(bi));
	    	circle.addMouseListener(new MouseClick(line, lineModified, 0));
	        size = circle.getPreferredSize();
	        circle.setBounds(temp.x*res.getFactor(), temp.y*res.getFactor(), size.width, size.height);
		}else{
	    	circle = new JLabel(ImageLoader.getMissionsImage(currentRes));
	    	circle.addMouseListener(new MouseClick(line, lineModified, 0));
	        size = circle.getPreferredSize();
	        circle.setBounds(temp.x*res.getFactor(), temp.y*res.getFactor(), size.width, size.height);
	    }
        
        globalMap.add(circle);
        globalMap.add(line);
        
        //other
        while(temp != mission.getFinish().getLocation()){
        	first = temp;
        	step = step.getNext().get(0);
        	temp = step.getLocation();
        	x1 = first.x*res.getFactor() + res.getFactor()/2;
    		y1 = first.y*res.getFactor() + res.getFactor()/2;
    		x2 = temp.x*res.getFactor() + res.getFactor()/2;
    		y2 = temp.y*res.getFactor() + res.getFactor()/2;
    		w = Math.abs(x1 - x2);
    		if(w == 0)
    			w = 1;
    		h = Math.abs(y1 - y2);
    		if(h == 0)
    			h = 1;
    		minX=x1<x2?x1:x2;
    		minY=y1<y2?y1:y2;
    		
    		//line
    		bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            g2d = (Graphics2D)bi.createGraphics();
            g2d.setPaint(Color.WHITE);
            g2d.draw(new Line2D.Double(x1-minX, y1-minY, x2-minX, y2-minY));
            g2d.dispose();
            line = new JLabel(new ImageIcon(bi));
            line.setBounds(minX, minY, w, h);
            
            //circle
            if(temp != mission.getFinish().getLocation()){
	            bi = new BufferedImage(res.getFactor(), res.getFactor(), BufferedImage.TYPE_INT_ARGB);
	            g2d = (Graphics2D)bi.createGraphics();
	            g2d.setPaint(new Color(255, 0, 0, 150));
	        	g2d.fill (new Ellipse2D.Double(0.34*res.getFactor(), 0.34*res.getFactor(), res.getFactor()/3, res.getFactor()/3));
	        	g2d.dispose();
	        	circle = new JLabel(new ImageIcon(bi));
	            size = circle.getPreferredSize();
	            circle.setBounds(temp.x*res.getFactor(), temp.y*res.getFactor(), size.width, size.height);
            }else{
	        	circle = new JLabel(ImageLoader.getMissionsImage(currentRes));
	            size = circle.getPreferredSize();
	            circle.setBounds(temp.x*res.getFactor(), temp.y*res.getFactor(), size.width, size.height);
            }
            globalMap.add(circle);
            globalMap.add(line);
        }
		
		return globalMap;
	}

	public void setResolution(Resolution res){
    	if(res != currentRes){
    		currentRes = res;
    		this.removeAll();
    		if(missionPanels.get(currentRes) == null){
    			missionPanels.put(currentRes, createMissionPanel(currentRes));
    		}
			this.add(missionPanels.get(currentRes));
    	}
    }
	
	public void refreshPanel(){
    	this.removeAll();
    	Resolution[] resolutions = Resolution.values();
    	for(int i = 0; i<resolutions.length; i++)
    		missionPanels.put(resolutions[i], null);
    	missionPanels.put(currentRes, this.createMissionPanel(currentRes));
    	this.add(missionPanels.get(currentRes));
    	this.revalidate();
    }

	@Override
	public void stateChanged(ResultEvent e) {
		switch(e.getType()){
		case WIN:
			engine.stepFinish();
			break;
		case LOSE:
			engine.undoStep();
			break;
		case RETREAT:
			engine.undoStep();
			break;
		case ENEMY_RETREAT:
			engine.stepFinish();
			break;
		case REWARD:
			refresh.refresh();
			break;
		default:
			//error
			break;
		}
		refreshPanel();
	}
	
	class MouseClick implements MouseListener{
		public MouseClick(JLabel correct, JLabel modified, int index){
			this.modifiedLabel = modified;
			this.correctLabel = correct;
			this.indexStep = index;
		}
		
		@Override
		public void mouseClicked(MouseEvent e) {
			try{
				engine.choseStep(indexStep);
				JFrame combat = new CombatFrame(MissionPanel.this, callerToBlock);
				callerToBlock.setEnabled(false);
	            combat.setVisible(true);
			}catch(IllegalStateException e1){
				//boh
			}
			refreshPanel();
		}

		@Override
		public void mouseEntered(MouseEvent e) {
			missionPanels.get(currentRes).remove(correctLabel);
			missionPanels.get(currentRes).add(modifiedLabel);
			refresh.refresh();
		}

		@Override
		public void mouseExited(MouseEvent e) {
			missionPanels.get(currentRes).remove(modifiedLabel);
			missionPanels.get(currentRes).add(correctLabel);
			refresh.refresh();
		}
		@Override
		public void mousePressed(MouseEvent e) {}
		@Override
		public void mouseReleased(MouseEvent e) {}
		
		private JLabel modifiedLabel;
		private JLabel correctLabel;
		private int indexStep;
	}
	
    private Resolution currentRes;
    private EnumMap<Resolution, JPanel> missionPanels;
	private MissionEngine engine;
	private RefreshListener refresh;
	private JFrame callerToBlock;
	private static final long serialVersionUID = 3115087779354989663L;
}
